/*
 * ObjectUtil.java        1.0     2009-6-24  17:10:21
 *
 * Copyright (c) 2004, 2005 Works Systems, Inc.
 * Copyright (c) 2004, 2005 Works Systems (Tianjin) Co., Ltd.
 * All rights reserved.
 *
 * This software is the confidential and proprietary information of
 * Works Systems, Inc and Works Systems (Tianjin) Co., Ltd. ("Confidential Information").  You shall not
 * disclose such Confidential Information and shall use it only in
 * accordance with the terms of the license agreement you entered into
 * with Works Systems.
 */
package com.letianpai.common.tool;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Iterator;

/**
 * Created by IntelliJ IDEA.
 * User: Chris.F
 * Date: 2009-6-24
 * Time: 17:10:21
 */
public final class ObjectUtil {

    public static boolean equals(Object obj1, Object obj2) {
        if (obj1 == obj2) return true;
        if (obj1 == null || obj2 == null) return false;
        return obj1.equals(obj2);
    }

    public static boolean notEquals(Object obj1, Object obj2) {
        return !equals(obj1, obj2);
    }

    public static <E> boolean equals(Collection<E> obj1, Collection<E> obj2) {
        if (obj1 == obj2) return true;
        if (obj1 == null || obj2 == null) return false;
        if (obj1.size() != obj2.size()) return false;

        Iterator<E> it1 = obj1.iterator();
        Iterator<E> it2 = obj2.iterator();
        while (it1.hasNext() && it2.hasNext()) {
            if (!equals(it1.next(), it2.next())) return false;
        }
        return true;
    }

    public static <E> boolean notEquals(Collection<E> obj1, Collection<E> obj2) {
        return !equals(obj1, obj2);
    }

    public static Object invoke(final Object obj, final String methodName,
                                final Class<?>[] parameterTypes, final Object... args) {
        if (obj == null)
            return null;
        try {
            Method m = obj.getClass().getMethod(methodName, parameterTypes);
            return m.invoke(obj, args);
        } catch (InvocationTargetException e) {
            throw new RuntimeException(
                    String.format("invoke method %s of class %s error", methodName, obj.getClass().getName()),
                    e.getCause()
            );
        } catch (Exception e) {
            System.err.println("invoke method error");
            e.printStackTrace(System.err);
        }
        return null;
    }

    public static Object getProperty(final Object obj, String expression) {
        if (obj == null)
            return null;
        String[] properties = StringUtil.split(expression, "\\.");
        if (properties.length == 0)
            return null;
        Object o = obj;
        try {
            for (String property : properties) {
                if (o == null)
                    return null;
                String methodName = buildGet(property);
                o = invoke(o, methodName, new Class[0], new Object[0]);
            }
        } catch (Exception e) {
            System.err.println("invoke method error");
            e.printStackTrace(System.err);
            return null;
        }
        return o;
    }

    public static <T> void setProperty(final Object obj, String expression, Class c, T value) {
        if (obj == null)
            return;
        if (StringUtil.isEmpty(expression))
            return;

        Object o = obj;
        String property = expression;

        int pos = expression.lastIndexOf(".");
        if (pos != -1) {
            o = getProperty(obj, expression.substring(0, pos));
            property = expression.substring(pos + 1);
        }
        try {
            String methodName = buildSet(property);
            invoke(o, methodName, new Class[]{c}, value);
        } catch (Exception e) {
            System.err.println("invoke method error");
            e.printStackTrace(System.err);
        }
    }

    private static String buildSet(String property) {
        return "set" + property.substring(0, 1).toUpperCase() + property.substring(1);
    }

    private static String buildGet(String property) {
        return "get" + property.substring(0, 1).toUpperCase() + property.substring(1);
    }

}
